package com.zenithmind.document.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zenithmind.document.mapper.DocumentAccessLogMapper;
import com.zenithmind.document.pojo.domain.DocumentAccessLog;
import com.zenithmind.document.pojo.dto.DocumentAccessLogCreateDTO;
import com.zenithmind.document.pojo.query.DocumentAccessLogQueryDTO;
import com.zenithmind.document.pojo.vo.DocumentAccessLogVO;
import com.zenithmind.document.service.DocumentAccessLogService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 文档访问日志服务实现类
 * 遵循单一职责原则：专注于访问日志管理
 * 遵循依赖倒置原则：依赖抽象接口而不是具体实现
 * 
 * @author ZenithMind Team
 * @since 2025-01-09
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class DocumentAccessLogServiceImpl extends ServiceImpl<DocumentAccessLogMapper, DocumentAccessLog> implements DocumentAccessLogService {

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentAccessLogVO recordAccess(DocumentAccessLogCreateDTO createDTO) {
        log.info("记录文档访问: documentId={}, userId={}, accessType={}", 
                createDTO.getDocumentId(), createDTO.getUserId(), createDTO.getAccessType());
        
        DocumentAccessLog accessLog = new DocumentAccessLog();
        BeanUtils.copyProperties(createDTO, accessLog);
        accessLog.setAccessTime(LocalDateTime.now());
        
        save(accessLog);
        
        return convertToVO(accessLog);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentAccessLogVO recordView(String documentId, String userId, String userAgent, String ipAddress) {
        log.info("记录文档查看: documentId={}, userId={}", documentId, userId);
        
        DocumentAccessLog accessLog = DocumentAccessLog.createViewLog(documentId, userId, userAgent, ipAddress);
        save(accessLog);
        
        return convertToVO(accessLog);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentAccessLogVO recordDownload(String documentId, String userId, String userAgent, String ipAddress) {
        log.info("记录文档下载: documentId={}, userId={}", documentId, userId);
        
        DocumentAccessLog accessLog = DocumentAccessLog.createDownloadLog(documentId, userId, userAgent, ipAddress);
        save(accessLog);
        
        return convertToVO(accessLog);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public DocumentAccessLogVO recordShare(String documentId, String userId, String shareType, String userAgent, String ipAddress) {
        log.info("记录文档分享: documentId={}, userId={}, shareType={}", documentId, userId, shareType);
        
        DocumentAccessLog accessLog = DocumentAccessLog.createShareLog(documentId, userId, shareType, userAgent, ipAddress);
        save(accessLog);
        
        return convertToVO(accessLog);
    }

    @Override
    public IPage<DocumentAccessLogVO> getAccessLogPage(DocumentAccessLogQueryDTO queryDTO) {
        log.info("分页查询访问日志");
        
        Page<DocumentAccessLogVO> page = new Page<>(queryDTO.getCurrent(), queryDTO.getSize());
        
        return baseMapper.selectAccessLogPageWithDetails(page, queryDTO);
    }

    @Override
    public List<DocumentAccessLogVO> getDocumentAccessLogs(String documentId, Integer limit) {
        log.info("获取文档访问日志: documentId={}", documentId);
        
        return baseMapper.selectDocumentAccessLogs(documentId, limit);
    }

    @Override
    public List<DocumentAccessLogVO> getUserAccessLogs(String userId, Integer limit) {
        log.info("获取用户访问日志: userId={}", userId);
        
        return baseMapper.selectUserAccessLogs(userId, limit);
    }

    @Override
    public Object getAccessStatistics(String documentId, Integer days) {
        log.info("获取访问统计: documentId={}, days={}", documentId, days);
        
        return baseMapper.selectAccessStatistics(documentId, days);
    }

    @Override
    public List<Object> getHotAccessDocuments(Integer days, Integer limit) {
        log.info("获取热门访问文档: days={}, limit={}", days, limit);
        
        return baseMapper.selectHotAccessDocuments(days, limit);
    }

    @Override
    public List<Object> getAccessTrend(String documentId, Integer days) {
        log.info("获取访问趋势: documentId={}, days={}", documentId, days);
        
        return baseMapper.selectAccessTrend(documentId, days);
    }

    @Override
    public Object getUserAccessBehavior(String userId, Integer days) {
        log.info("获取用户访问行为分析: userId={}, days={}", userId, days);
        
        return baseMapper.selectUserAccessBehavior(userId, days);
    }

    @Override
    public List<Object> getIpAccessStatistics(Integer days, Integer limit) {
        log.info("获取IP访问统计: days={}, limit={}", days, limit);
        
        return baseMapper.selectIpAccessStatistics(days, limit);
    }

    @Override
    public List<Object> getDeviceAccessStatistics(Integer days) {
        log.info("获取设备访问统计: days={}", days);
        
        return baseMapper.selectDeviceAccessStatistics(days);
    }

    @Override
    public List<Object> getBrowserAccessStatistics(Integer days) {
        log.info("获取浏览器访问统计: days={}", days);
        
        return baseMapper.selectBrowserAccessStatistics(days);
    }

    @Override
    public List<Object> getAccessTimeDistribution(Integer days) {
        log.info("获取访问时间分布: days={}", days);
        
        return baseMapper.selectAccessTimeDistribution(days);
    }

    @Override
    public Boolean detectAbnormalAccess(String documentId, String userId, String ipAddress) {
        log.info("检测异常访问: documentId={}, userId={}, ipAddress={}", documentId, userId, ipAddress);
        
        return baseMapper.detectAbnormalAccess(documentId, userId, ipAddress);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer cleanupExpiredLogs(Integer retentionDays) {
        log.info("清理过期访问日志: retentionDays={}", retentionDays);
        
        return baseMapper.cleanupExpiredLogs(retentionDays);
    }

    @Override
    public Object exportAccessLogs(DocumentAccessLogQueryDTO queryDTO) {
        log.info("导出访问日志");
        
        return baseMapper.exportAccessLogs(queryDTO);
    }

    @Override
    public Object getRealTimeAccessStatistics() {
        log.info("获取实时访问统计");
        
        return baseMapper.selectRealTimeAccessStatistics();
    }

    @Override
    public List<Object> getAccessLocationDistribution(Integer days) {
        log.info("获取访问地域分布: days={}", days);
        
        return baseMapper.selectAccessLocationDistribution(days);
    }

    @Override
    public List<Object> getAccessSourceStatistics(Integer days, Integer limit) {
        log.info("获取访问来源统计: days={}, limit={}", days, limit);
        
        return baseMapper.selectAccessSourceStatistics(days, limit);
    }

    @Override
    public List<Object> getAccessPathAnalysis(String userId, Integer days) {
        log.info("获取访问路径分析: userId={}, days={}", userId, days);
        
        return baseMapper.selectAccessPathAnalysis(userId, days);
    }

    @Override
    public Object getAccessSessionStatistics(Integer days) {
        log.info("获取访问会话统计: days={}", days);
        
        return baseMapper.selectAccessSessionStatistics(days);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer batchRecordAccess(List<DocumentAccessLogCreateDTO> accessLogs) {
        log.info("批量记录访问: size={}", accessLogs.size());
        
        List<DocumentAccessLog> logs = accessLogs.stream()
                .map(dto -> {
                    DocumentAccessLog log = new DocumentAccessLog();
                    BeanUtils.copyProperties(dto, log);
                    log.setAccessTime(LocalDateTime.now());
                    return log;
                })
                .toList();
        
        return baseMapper.batchInsertAccessLogs(logs);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean syncAccessStatistics() {
        log.info("同步访问统计");
        
        return baseMapper.syncAccessStatistics() > 0;
    }

    /**
     * 转换为VO对象
     */
    private DocumentAccessLogVO convertToVO(DocumentAccessLog accessLog) {
        DocumentAccessLogVO vo = new DocumentAccessLogVO();
        BeanUtils.copyProperties(accessLog, vo);
        return vo;
    }
}
